﻿using System.Data.SQLite;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;

namespace DetectingKinectSencor._50_Evaluation
{
    public class EvaluationData
    {
        public static OpenGestureData openGestureData { get; set; }
        public static HandsBelowWaistlineData handsBelowWaistlineData { get; set; }
        public static MovingData movingData { get; set; }
        public static ViewingDirectionData viewingDirectionData { get; set; }
        public static SlideChangeData slideChangeData { get; set; }
        public static VideoDetectedData videoDetectedData { get; set; }
        public static ImageDetectedData imageDetectedData { get; set; }
        public static WordsPerMinuteData oralCommunication { get; set; }

        private static int captureTimeListLength;
        static SQLiteConnection databaseConnectionInternal;

        public static TrackingSequences savedCapturesList;


         public static void loadData(SQLiteConnection databaseConnection, int lengthCaptureTimeList)
        {
             databaseConnectionInternal = databaseConnection;

             captureTimeListLength = lengthCaptureTimeList;

             // Load the data from each table
             loadGestureData();
             loadHandsBelowWaistlineData();
             loadMovingData();
             loadViewingDirectionData();
             loadSlidesChangeData();
             loadVideoDetectedData();
             loadPictureDetectedData();
             loadOralCommunicationData();
        }

         private static void loadOralCommunicationData()
         {
             // The array needs to be as big as the captureTimeList, +1 because  in the while loop the i must be incremented before 
             // the new object is created, this saves an if statement to check if is the first round or not, but than the array
             // needs to have one space more, because the zero entry of the array is null
             CaptureTime[] tempCaptureTimeObject = new CaptureTime[captureTimeListLength + 1];
             int i = 0;

             // Create a new command
             SQLiteCommand getDataSqliteCommand = databaseConnectionInternal.CreateCommand();

             // Get data from the table
             getDataSqliteCommand.CommandText = "SELECT * FROM oral_communication";

             // Get back the reader
             SQLiteDataReader dataReaderSqlite = getDataSqliteCommand.ExecuteReader();

             oralCommunication = new WordsPerMinuteData();

             // Read the data from the DB and saves it in the WordsPerMinute List
             readDataFromDatabaseOralCommunication(ref tempCaptureTimeObject, dataReaderSqlite, ref i);

             //Add the sequences from the temp array to the list of the wordsPerMinute Object
             // Starts at 1 because the first entry is null
             for (int j = 1; j <= i; j++)
             {
                 oralCommunication.trackingSequences.Add(tempCaptureTimeObject[j]);
             }

             // Release the command
             getDataSqliteCommand.Dispose();

             // Close the Reader
             dataReaderSqlite.Close();
         }



         private static void loadViewingDirectionData()
         {
             // The array needs to be as big as the captureTimeList, +1 because  in the while loop the i must be incremented before 
             // the new object is created, this saves an if statement to check if is the first round or not, but than the array
             // needs to have one space more, because the zero entry of the array is null
             CaptureTime[] tempCaptureTimeObject = new CaptureTime[captureTimeListLength + 1];
             int i = 0;

             // Create a new command
             SQLiteCommand getDataSqliteCommand = databaseConnectionInternal.CreateCommand();

             // Get data from the table
             getDataSqliteCommand.CommandText = "SELECT * FROM looked_away";

             // Get back the reader
             SQLiteDataReader dataReaderSqlite = getDataSqliteCommand.ExecuteReader();

             viewingDirectionData = new ViewingDirectionData();

             // Read the data from the DB and saves it in the viewiewingDirection List
             readDataFromDatabase(ref tempCaptureTimeObject,dataReaderSqlite, ref i);

             //Add the sequences from the temp array to the list of the viewingDirectionData Object
             // Starts at 1 because the first entry is null
             for (int j = 1; j <= i; j++)
             {
                 viewingDirectionData.trackingSequences.Add(tempCaptureTimeObject[j]);
             }

             // Release the command
             getDataSqliteCommand.Dispose();

             // Close the Reader
             dataReaderSqlite.Close();
         }




         private static void readDataFromDatabase(ref CaptureTime[] tempCaptureTimeObject, SQLiteDataReader dataReaderSqlite, ref int i)
         {
             DateTime previousCapturetime = new DateTime();

             try
             {
                 // Read() returns true if there is still a result line to read
                 while (dataReaderSqlite.Read())
                 {
                     DateTime tempCaptureTime = Convert.ToDateTime(dataReaderSqlite["capturedTime"]);

                     DateTime tempTimePoint = Convert.ToDateTime(dataReaderSqlite["timepoint"]);

                     int tempTimespanMinute = Convert.ToInt32(dataReaderSqlite["timespanMinute"]);
                     int tempTimespanSec = Convert.ToInt32(dataReaderSqlite["timespanSec"]);

                     TimeSpan tempTimeSpan = new TimeSpan(0, tempTimespanMinute, tempTimespanSec);

                     // Check if there is a new capture time which means a new sequence and hence increment i
                     if (tempCaptureTime != previousCapturetime)
                     {
                         i++;

                         // If there is a new capturetime, a new object is created and the corresponding timePoint/timeSpan is saved
                         tempCaptureTimeObject[i] = new CaptureTime(tempCaptureTime);
                         tempCaptureTimeObject[i].timePoints.Add(new TimePoint(tempTimePoint, tempTimeSpan));
                     }
                     else
                     {
                         // This means it is the same capturetime (sequence) so only the timepoints and timespan are added
                         tempCaptureTimeObject[i].timePoints.Add(new TimePoint(tempTimePoint, tempTimeSpan));
                     }

                     // Save the current capturetime to the previous to check in the next round if there is a new capture time
                     previousCapturetime = tempCaptureTime;
                 }
             }
             catch (Exception ex)
             {
                 MessageBox.Show("Error getting data from viewing direction table: " + ex.Message);
             }
         }


        // The words per minute is a special case, because this has an additional attribute which holds the number of words per minute
        // because a DB entry for every recognized word, would not make sense and would need too much ressources and DB accesses
         private static void readDataFromDatabaseOralCommunication(ref CaptureTime[] tempCaptureTimeObject, SQLiteDataReader dataReaderSqlite, ref int i)
         {
             DateTime previousCapturetime = new DateTime();

             try
             {
                 // Read() returns true if there is still a result line to read
                 while (dataReaderSqlite.Read())
                 {
                     DateTime tempCaptureTime = Convert.ToDateTime(dataReaderSqlite["capturedTime"]);

                     DateTime tempTimePoint = Convert.ToDateTime(dataReaderSqlite["timepoint"]);

                     int tempTimespanMinute = Convert.ToInt32(dataReaderSqlite["timespanMinute"]);
                     int tempTimespanSec = Convert.ToInt32(dataReaderSqlite["timespanSec"]);

                     int tempWordsPerMinute = Convert.ToInt32(dataReaderSqlite["wordsPerMinute"]);

                     TimeSpan tempTimeSpan = new TimeSpan(0, tempTimespanMinute, tempTimespanSec);

                     // Check if there is a new capture time which means a new sequence and hence increment i
                     if (tempCaptureTime != previousCapturetime)
                     {
                         i++;

                         // If there is a new capturetime, a new object is created and the corresponding timePoint/timeSpan is saved
                         tempCaptureTimeObject[i] = new CaptureTime(tempCaptureTime);
                         tempCaptureTimeObject[i].timePoints.Add(new TimePoint(tempTimePoint, tempTimeSpan, tempWordsPerMinute));
                     }
                     else
                     {
                         // This means it is the same capturetime (sequence) so only the timepoints and timespan are added
                         tempCaptureTimeObject[i].timePoints.Add(new TimePoint(tempTimePoint, tempTimeSpan, tempWordsPerMinute));
                     }

                     // Save the current capturetime to the previous to check in the next round if there is a new capture time
                     previousCapturetime = tempCaptureTime;
                 }
             }
             catch (Exception ex)
             {
                 MessageBox.Show("Error getting data from viewing direction table: " + ex.Message);
             }
         }

        

         private static void loadMovingData()
         {
             // The array needs to be as big as the captureTimeList, +1 because  in the while loop the i must be incremented before 
             // the new object is created, this saves an if statement to check if is the first round or not, but than the array
             // needs to have one space more, because the zero entry of the array is null
             CaptureTime[] tempCaptureTimeObject = new CaptureTime [captureTimeListLength+1];
             int i=0;

             // Create a new command
             SQLiteCommand getDataSqliteCommand = databaseConnectionInternal.CreateCommand();

             // Get gestures data
             getDataSqliteCommand.CommandText = "SELECT * FROM movement";
             
             // Get back the reader
             SQLiteDataReader dataReaderSqlite = getDataSqliteCommand.ExecuteReader();

             movingData = new MovingData();

             // Read the data from the DB and saves it in the viewiewingDirection List
             readDataFromDatabase(ref tempCaptureTimeObject,dataReaderSqlite, ref i);

             //Add the sequences from the temp array to the list of the movingData Object
             // Starts at 1 because the first entry is null
             for (int j = 1; j <= i; j++)
             {
                movingData.trackingSequences.Add(tempCaptureTimeObject[j]);
             }

             // Release the command
             getDataSqliteCommand.Dispose();

             // Close the Reader
             dataReaderSqlite.Close();
         }




         private static void loadHandsBelowWaistlineData()
         {
             // The array needs to be as big as the captureTimeList, +1 because  in the while loop the i must be incremented before 
             // the new object is created, this saves an if statement to check if is the first round or not, but than the array
             // needs to have one space more, because the zero entry of the array is null
             CaptureTime[] tempCaptureTimeObject = new CaptureTime[captureTimeListLength + 1];
             int i = 0;

             // Create a new command
             SQLiteCommand getDataSqliteCommand = databaseConnectionInternal.CreateCommand();

             // Get gestures data
             getDataSqliteCommand.CommandText = "SELECT * FROM hands_below_wasteline";

             // Get back the reader
             SQLiteDataReader dataReaderSqlite = getDataSqliteCommand.ExecuteReader();

             handsBelowWaistlineData = new HandsBelowWaistlineData();

             // Read the data from the DB and saves it in the viewiewingDirection List
             readDataFromDatabase(ref tempCaptureTimeObject, dataReaderSqlite, ref i);

             //Add the sequences from the temp array to the list of the handsBelowWaistLine Object
             // Starts at 1 because the first entry is null
             for (int j = 1; j <= i; j++)
             {
                 handsBelowWaistlineData.trackingSequences.Add(tempCaptureTimeObject[j]);
             }

             // Release the command
             getDataSqliteCommand.Dispose();

             // Close the Reader
             dataReaderSqlite.Close();
         }






         private static void loadGestureData()
         {   // The array needs to be as big as the captureTimeList, +1 because  in the while loop the i must be incremented before 
             // the new object is created, this saves an if statement to check if is the first round or not, but than the array
             // needs to have one space more, because the zero entry of the array is null
             CaptureTime[] tempCaptureTimeObject = new CaptureTime[captureTimeListLength + 1];

             int i = 0;

             // Create a new command
             SQLiteCommand getDataSqliteCommand = databaseConnectionInternal.CreateCommand();

             // Get gestures data
             getDataSqliteCommand.CommandText = "SELECT * FROM open_gestures";

             // Get back the reader
             SQLiteDataReader dataReaderSqlite = getDataSqliteCommand.ExecuteReader();

             openGestureData = new OpenGestureData();

             // Read the data from the DB and saves it in the viewiewingDirection List
             readDataFromDatabase(ref tempCaptureTimeObject, dataReaderSqlite, ref i);

             // Starts at 1 because the first entry is null
             for (int j = 1; j <= i; j++)
             {
                 openGestureData.trackingSequences.Add(tempCaptureTimeObject[j]);
             }

             // Release the command
             getDataSqliteCommand.Dispose();

             // Close the Reader
             dataReaderSqlite.Close();
         }



         private static void loadSlidesChangeData()
         {   // The array needs to be as big as the captureTimeList, +1 because  in the while loop the i must be incremented before 
             // the new object is created, this saves an if statement to check if is the first round or not, but than the array
             // needs to have one space more, because the zero entry of the array is null
             CaptureTime[] tempCaptureTimeObject = new CaptureTime[captureTimeListLength + 1];

             int i = 0;

             // Create a new command
             SQLiteCommand getDataSqliteCommand = databaseConnectionInternal.CreateCommand();

             // Get gestures data
             getDataSqliteCommand.CommandText = "SELECT * FROM slides_change";

             // Get back the reader
             SQLiteDataReader dataReaderSqlite = getDataSqliteCommand.ExecuteReader();

             slideChangeData = new SlideChangeData();

             // Read the data from the DB and saves it in the viewiewingDirection List
             readDataFromDatabase(ref tempCaptureTimeObject, dataReaderSqlite, ref i);

             // Add the sequences from the temp array to the list of the slideChangeData Object
             // Starts at 1 because the first entry is null
             for (int j = 1; j <= i; j++)
             {
                 slideChangeData.trackingSequences.Add(tempCaptureTimeObject[j]);
             }

             // Release the command
             getDataSqliteCommand.Dispose();

             // Close the Reader
             dataReaderSqlite.Close();
         }



         private static void loadVideoDetectedData()
         {   // The array needs to be as big as the captureTimeList, +1 because  in the while loop the i must be incremented before 
             // the new object is created, this saves an if statement to check if is the first round or not, but than the array
             // needs to have one space more, because the zero entry of the array is null
             CaptureTime[] tempCaptureTimeObject = new CaptureTime[captureTimeListLength + 1];

             int i = 0;

             // Create a new command
             SQLiteCommand getDataSqliteCommand = databaseConnectionInternal.CreateCommand();

             // Get gestures data
             getDataSqliteCommand.CommandText = "SELECT * FROM slides_video";

             // Get back the reader
             SQLiteDataReader dataReaderSqlite = getDataSqliteCommand.ExecuteReader();

             videoDetectedData = new VideoDetectedData();

             // Read the data from the DB and saves it in the viewiewingDirection List
             readDataFromDatabase(ref tempCaptureTimeObject, dataReaderSqlite, ref i);

             //Add the sequences from the temp array to the list of the videoDetected Object
             // Starts at 1 because the first entry is null
             for (int j = 1; j <= i; j++)
             {
                 videoDetectedData.trackingSequences.Add(tempCaptureTimeObject[j]);
             }

             // Release the command
             getDataSqliteCommand.Dispose();

             // Close the Reader
             dataReaderSqlite.Close();
         }




         private static void loadPictureDetectedData()
         {   // The array needs to be as big as the captureTimeList, +1 because  in the while loop the i must be incremented before 
             // the new object is created, this saves an if statement to check if is the first round or not, but than the array
             // needs to have one space more, because the zero entry of the array is null
             CaptureTime[] tempCaptureTimeObject = new CaptureTime[captureTimeListLength + 1];

             int i = 0;

             // Create a new command
             SQLiteCommand getDataSqliteCommand = databaseConnectionInternal.CreateCommand();

             // Get gestures data
             getDataSqliteCommand.CommandText = "SELECT * FROM slides_picture";

             // Get back the reader
             SQLiteDataReader dataReaderSqlite = getDataSqliteCommand.ExecuteReader();

             imageDetectedData = new ImageDetectedData();

             // Read the data from the DB and saves it in the viewiewingDirection List
             readDataFromDatabase(ref tempCaptureTimeObject, dataReaderSqlite, ref i);

             //Add the sequences from the temp array to the list of the pictureDetectedData Object
             // Starts at 1 because the first entry is null
             for (int j = 1; j <= i; j++)
             {
                 imageDetectedData.trackingSequences.Add(tempCaptureTimeObject[j]);
             }

             // Release the command
             getDataSqliteCommand.Dispose();

             // Close the Reader
             dataReaderSqlite.Close();
         }




         internal static TrackingSequences loadList(SQLiteConnection databaseConnection)
         {
             savedCapturesList = new TrackingSequences();

             // Create a new command
             SQLiteCommand getDataSqliteCommand = databaseConnection.CreateCommand();

             getDataSqliteCommand.CommandText = "SELECT * FROM captured_time";

             // Get back the reader
             SQLiteDataReader dataReaderSqlite = getDataSqliteCommand.ExecuteReader();

             try
             {
                 // Read() returns true if there is still a result line to read
                 while (dataReaderSqlite.Read())
                 {
                     DateTime tempStartDateTime = Convert.ToDateTime(dataReaderSqlite["capturedTime"]);
                     DateTime tempEndDateTime = Convert.ToDateTime(dataReaderSqlite["stoppedTime"]);

                     savedCapturesList.startCapture.Add(tempStartDateTime);

                     savedCapturesList.endCapture.Add(tempEndDateTime);
                 }
             }
             catch (Exception ex)
             {
                 MessageBox.Show("Error getting data from trackingTime table: " + ex.Message);
             }

             // Release the command
             getDataSqliteCommand.Dispose();

             // Close the Reader
             dataReaderSqlite.Close();

             return savedCapturesList;
         }
    }




    public class OpenGestureData
    {
        public List<CaptureTime> trackingSequences { get; set; }

        internal OpenGestureData()
        {
            trackingSequences = new List<CaptureTime>();
        }
    }

    public class HandsBelowWaistlineData
    {
        public List<CaptureTime> trackingSequences { get; set; }

        internal HandsBelowWaistlineData()
        {
            trackingSequences = new List<CaptureTime>();
        }
    }

    public class MovingData
    {
        public List<CaptureTime> trackingSequences { get; set; }

        internal MovingData()
        {
            trackingSequences = new List<CaptureTime>();
        }
    }

    public class SlideChangeData
    {
        public List<CaptureTime> trackingSequences { get; set; }

        internal SlideChangeData()
        {
            trackingSequences = new List<CaptureTime>();
        }
    }

    public class VideoDetectedData
    {
        public List<CaptureTime> trackingSequences { get; set; }

        internal VideoDetectedData()
        {
            trackingSequences = new List<CaptureTime>();
        }
    }

    public class ImageDetectedData
    {
        public List<CaptureTime> trackingSequences { get; set; }

        internal ImageDetectedData()
        {
            trackingSequences = new List<CaptureTime>();
        }
    }

    public class ViewingDirectionData
    {
        public List<CaptureTime> trackingSequences { get; set; }

        internal ViewingDirectionData()
        {
            trackingSequences = new List<CaptureTime>();
        }
    }

    public class WordsPerMinuteData
    {
        public List<CaptureTime> trackingSequences { get; set; }

        internal WordsPerMinuteData()
        {
            trackingSequences = new List<CaptureTime>();
        }
    }

    public class TrackingSequences
    {
        public List<DateTime> startCapture { get; set; }
        public List<DateTime> endCapture { get; set; }

        internal TrackingSequences()
        {
            startCapture = new List<DateTime>();
            endCapture = new List<DateTime>();
        }
    }

    public class CaptureTime
    {
        public List<TimePoint> timePoints { get; set; }
        public DateTime captureTime { get; set; }

        public CaptureTime(DateTime captureTime)
        {
            timePoints = new List<TimePoint>();
            this.captureTime = captureTime;
        }
    }
    public class TimePoint
    {
        public DateTime timePoint { get; set; }
        public TimeSpan timeSpan { get; set; }
        public int wordsPerMinute { get; set; }

        public TimePoint(DateTime timePoint, TimeSpan timeSpan)
        {
            this.timePoint = timePoint;
            this.timeSpan = timeSpan;
        }

        public TimePoint(DateTime timePoint, TimeSpan timeSpan, int wordsPerMinute)
        {
            this.timePoint = timePoint;
            this.timeSpan = timeSpan;
            this.wordsPerMinute = wordsPerMinute;
        }
        
    }
}
